/*
 * @Author: LVGRAPE
 * @LastEditors: LVGRAPE
 */

#ifndef __CRC_FUNC_DEF_H__
#define __CRC_FUNC_DEF_H__


typedef unsigned char BOOL;
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint32;

uint8 Reflect8(uint8 val);
uint16 Reflect16(uint16 val);
uint32 Reflect32(uint32 val);
uint8 crc_8(uint8 crc, uint8* pdata, uint32 len);

/**
Name                 Polynomial Initial    FinalXor   InputReflected ResultReflected
CRC8                 0x07       0x00       0x00       false          false
CRC8_SAE_J1850       0x1D       0xFF       0xFF       false          false
CRC8_SAE_J1850_ZERO  0x1D       0x00       0x00       false          false
CRC8_8H2F            0x2F       0xFF       0xFF       false          false
CRC8_CDMA2000        0x9B       0xFF       0x00       false          false
CRC8_DARC            0x39       0x00       0x00       true           true
CRC8_DVB_S2          0xD5       0x00       0x00       false          false
CRC8_EBU             0x1D       0xFF       0x00       true           true
CRC8_ICODE           0x1D       0xFD       0x00       false          false
CRC8_ITU             0x07       0x00       0x55       false          false
CRC8_MAXIM           0x31       0x00       0x00       true           true
CRC8_ROHC            0x07       0xFF       0x00       true           true
CRC8_WCDMA           0x9B       0x00       0x00       true           true
CRC16_CCIT_ZERO      0x1021     0x0000     0x0000     false          false
CRC16_ARC            0x8005     0x0000     0x0000     true           true
CRC16_AUG_CCITT      0x1021     0x1D0F     0x0000     false          false
CRC16_BUYPASS        0x8005     0x0000     0x0000     false          false
CRC16_CCITT_FALSE    0x1021     0xFFFF     0x0000     false          false
CRC16_CDMA2000       0xC867     0xFFFF     0x0000     false          false
CRC16_DDS_110        0x8005     0x800D     0x0000     false          false
CRC16_DECT_R         0x0589     0x0000     0x0001     false          false
CRC16_DECT_X         0x0589     0x0000     0x0000     false          false
CRC16_DNP            0x3D65     0x0000     0xFFFF     true           true
CRC16_EN_13757       0x3D65     0x0000     0xFFFF     false          false
CRC16_GENIBUS        0x1021     0xFFFF     0xFFFF     false          false
CRC16_MAXIM          0x8005     0x0000     0xFFFF     true           true
CRC16_MCRF4XX        0x1021     0xFFFF     0x0000     true           true
CRC16_RIELLO         0x1021     0xB2AA     0x0000     true           true
CRC16_T10_DIF        0x8BB7     0x0000     0x0000     false          false
CRC16_TELEDISK       0xA097     0x0000     0x0000     false          false
CRC16_TMS37157       0x1021     0x89EC     0x0000     true           true
CRC16_USB            0x8005     0xFFFF     0xFFFF     true           true
CRC16_A              0x1021     0xC6C6     0x0000     true           true
CRC16_KERMIT         0x1021     0x0000     0x0000     true           true
CRC16_MODBUS         0x8005     0xFFFF     0x0000     true           true
CRC16_X_25           0x1021     0xFFFF     0xFFFF     true           true
CRC16_XMODEM         0x1021     0x0000     0x0000     false          false
CRC32                0x04C11DB7 0xFFFFFFFF 0xFFFFFFFF true           true
CRC32_BZIP2          0x04C11DB7 0xFFFFFFFF 0xFFFFFFFF false          false
CRC32_C              0x1EDC6F41 0xFFFFFFFF 0xFFFFFFFF true           true
CRC32_D              0xA833982B 0xFFFFFFFF 0xFFFFFFFF true           true
CRC32_MPEG2          0x04C11DB7 0xFFFFFFFF 0x00000000 false          false
CRC32_POSIX          0x04C11DB7 0x00000000 0xFFFFFFFF false          false
CRC32_Q              0x814141AB 0x00000000 0x00000000 false          false
CRC32_JAMCRC         0x04C11DB7 0xFFFFFFFF 0x00000000 true           true
CRC32_XFER           0x000000AF 0x00000000 0x00000000 false          false
*/

/**
 * @brief CRC function definition: func(pdata, len, initial, finalXor, inputReflected, resultReflected)
 *
 *
 */
#define DEF_CRC_FUNC(func, width, crcTable)                                                         \
uint##width func(const uint8 *pdata, uint32_t len,                                                  \
uint##width initial, uint##width finalXor,                                                          \
BOOL inputReflected, BOOL resultReflected)                                                          \
{                                                                                                   \
    uint##width crc = initial;                                                                      \
    uint##width temp1 = 0, temp2 = 0, pos = 0;                                                      \
    const uint##width *pTable = crcTable;                                                           \
    for(int i = 0; i < len; i++)                                                                    \
    {                                                                                               \
        uint##width curByte = pdata[i];                                                             \
        if(inputReflected)                                                                          \
        {                                                                                           \
          curByte = Reflect8(pdata[i]);                                                             \
        }                                                                                           \
        /* update the MSB of crc value with next input byte */                                      \
        temp1 = (crc ^ (curByte << (width - 8)));                                                   \
        /* this MSB byte value is the index into the lookup table */                                \
        pos = (temp1 >> (width - 8)) & 0xFF;                                                        \
        /* shift out this index */                                                                  \
        temp2 = (temp1 << 8);                                                                       \
        /* XOR-in remainder from lookup table using the calculated index */                         \
        crc = (temp2 ^ pTable[pos]);                                                                \
    }                                                                                               \
    if(resultReflected)                                                                             \
    {                                                                                               \
        crc = Reflect##width(crc);                                                                  \
    }                                                                                               \
    return (crc ^ finalXor);                                                                        \
}
#endif
